package com.gitee.feizns.quickstart.web.filter;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.MediaType;
import org.springframework.lang.NonNull;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.ContentCachingRequestWrapper;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * 缓存请求正文过滤器
 * @author feizns
 * @since 2025/10/14
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CachingRequestBodyFilter extends OncePerRequestFilter {

    /**
     * 介质类型
     */
    private final Set<MediaType> supportMediaTypes;

    public CachingRequestBodyFilter(MediaType... mediaTypes) {
        supportMediaTypes = new LinkedHashSet<>(Arrays.asList(mediaTypes));
    }

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull FilterChain chain) throws ServletException, IOException {
        if ( !(request instanceof ContentCachingRequestWrapper) && supportMediaType(request.getContentType()) )
            request = new ContentCachingRequestWrapper(request);
        chain.doFilter(request, response);
    }

    /**
     * 支持介质类型
     * @param mediaType 介质类型
     * @return boolean
     */
    public boolean supportMediaType(String mediaType) {
        if ( mediaType != null ) {
            MediaType type = MediaType.parseMediaType(mediaType);
            return supportMediaTypes
                    .stream()
                    .anyMatch(supportMediaType -> supportMediaType.isCompatibleWith(type));
        }
        return false;
    }

}
